/*
'  DotNetNuke -  http://www.dotnetnuke.com
'  Copyright (c) 2002-2011
'  by DotNetNuke Corporation
' 
'  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
'  documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
'  the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
'  to permit persons to whom the Software is furnished to do so, subject to the following conditions:
' 
'  The above copyright notice and this permission notice shall be included in all copies or substantial portions 
'  of the Software.
' 
'  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
'  TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
'  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
'  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
'  DEALINGS IN THE SOFTWARE.
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Communications;
using DotNetNuke.Security;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;
using DotNetNuke.Modules.Store.Admin;
using DotNetNuke.Modules.Store.Cart;
using DotNetNuke.Modules.Store.Components;
using DotNetNuke.Modules.Store.Customer;
using DotNetNuke.Modules.Store.Providers;
using DotNetNuke.Modules.Store.Providers.Cart;
using DotNetNuke.Modules.Store.Providers.Address;
using DotNetNuke.Modules.Store.Providers.Address.DefaultAddressProvider;
using DotNetNuke.Modules.Store.Providers.Shipping;
using DotNetNuke.Modules.Store.Providers.Tax;

namespace DotNetNuke.Modules.Store.WebControls
{
	/// <summary>
	/// Summary description for Account.
	/// </summary>
    //
    public partial class Checkout : StoreControlBase, ICheckoutControl, IStoreTabedControl
	{
		#region Controls

		protected AddressCheckoutControlBase addressCheckoutControl;
		protected ICheckoutControl taxControl;
		protected ICheckoutControl shippingControl;
		protected PaymentControlBase paymentControl;

		#endregion       

		#region Private/Protected Declarations

        private static string CookieName = "DotNetNuke_Store_Portal_";
        private ModuleSettings moduleSettings;
        private OrderInfo _order = null;
        private bool _includeVAT = false;
        private NumberFormatInfo LocalFormat = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone();
        private OrderController orderController = new OrderController();
        private AddressController addressController = new AddressController();
        private int lastStep = 3;
        private string templatePath;
        //private bool createAccount;

		#endregion

		#region Web Form Designer generated code

		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);
		}
		
		/// <summary>
		///		Required method for Designer support - do not modify
		///		the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
        }

		#endregion

        #region Public Properties

        public int LastStep
        {
            get { return lastStep; }
        }

        public int CheckoutStep
        {
            get { return (int)ViewState["StoreCheckoutStep"]; }
            set { ViewState["StoreCheckoutStep"] = value; }
        }

        #endregion

        #region Events

        protected void Page_Load(object sender, System.EventArgs e)
		{
            // On first load
            if (IsPostBack == false)
            {
                // Check if SSL is required
                if (forceSSL())
                    SSLHelper.RequestSecurePage();
                // Init checkout step
                CheckoutStep = 1;
            }
            // Various Init
            if (StoreSettings.CurrencySymbol != string.Empty)
            {
                LocalFormat.CurrencySymbol = StoreSettings.CurrencySymbol;
            }

            templatePath = CssTools.GetTemplatePath(this, StoreSettings.PortalTemplates);

            moduleSettings = new ModuleSettings(ModuleId, TabId);
            _includeVAT = moduleSettings.MainCart.IncludeVAT;

            // Load controls
            loadAddressControl();
            loadCartControl();
            loadShippingCheckoutControl();
            loadTaxCheckoutControl();
            loadPaymentControl();
            // Check if the customer returns from payment
            if (Request.QueryString["GatewayExit"] == null)
            {
                // NO: Retrieve order from cookie or create a new order
                Order = GetExistingOrder(GetOrderIDFromCookie(), true);
                if (Order == null)
                    Order = CreateOrder();
            }
            else
            {
                // YES: Retrieve order from querystring
                if (Request.QueryString["OrderID"] != null)
                {
                    int orderID = int.Parse(Request.QueryString["OrderID"]);
                    Order = GetExistingOrder(orderID, false);
                    if (Order != null)
                    {
                        // Display Done step
                        CheckoutStep = 4;
                    }
                    else
                    {
                        // Display ERROR!!!
                        divStoreCheckoutSteps.Visible = false;
                        plhCheckout.Visible = false;
                        plhError.Visible = true;
                        lblError.Text = "ERROR!!!";
                        plhCheckoutNavigation.Visible = false;
                    }
                }
            }
            // Display the needed step
            GoToStep(CheckoutStep);
		}

        protected void paymentControl_AwaitingPayment(object sender, EventArgs e)
        {
            // Update Order Result
            updateOrderResult(Localization.GetString("AwaitingPayment", this.LocalResourceFile));
        }

        protected void paymentControl_PaymentRequiresConfirmation(object sender, EventArgs e)
        {
            // Update Order Result
            updateOrderResult(Localization.GetString("PaymentRequiresConfirmation", this.LocalResourceFile));
        }

        protected void paymentControl_PaymentSucceeded(object sender, EventArgs e)
		{
            // Update Order Result
            updateOrderResult(Localization.GetString("PaymentSucceeded", this.LocalResourceFile));
        }

        protected void paymentControl_PaymentCancelled(object sender, EventArgs e)
		{
            // Update Order Result
            updateOrderResult(Localization.GetString("PaymentCancelled", this.LocalResourceFile));
        }

        protected void paymentControl_PaymentFailed(object sender, EventArgs e)
		{
            // Update Order Result
            updateOrderResult(Localization.GetString("PaymentFailed", this.LocalResourceFile));
        }

        protected void ctlAddressCheckout_BillingAddressChanged(object sender, AddressEventArgs e)
        {
            IAddressInfo address = e.address;
            UpdateAddresses(address, ShippingAddress);
        }

        protected void ctlAddressCheckout_ShippingAddressChanged(object sender, AddressEventArgs e)
        {
            IAddressInfo address = e.address;
            UpdateAddresses(BillingAddress, address);
        }

		/// <summary>
		/// This event should occur each time a change is made to the cart.  
		/// All of the Checkout controls should be updated with the new cart information and the 
		/// order updated.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
        protected void cartControl_EditComplete(object sender, EventArgs e)
		{
            CartInfo cart = CurrentCart.GetInfo(PortalId, StoreSettings.SecureCookie);
            if (cart != null && cart.Items > 0)
            {
                Order = orderController.UpdateOrderDetails(Order.OrderID, cart.CartID);
                CalculateTaxandShipping(Order, BillingAddress, ShippingAddress);
                updateCheckoutOrder(Order);
            }
            else
            {
                Response.Redirect(Globals.NavigateURL(StoreSettings.StorePageID));                
            }
		}

        protected void StoreAccountCheckoutPrevious_Click(object sender, EventArgs e)
        {
            int step = CheckoutStep;
            bool update = step == 3;
            step--;
            CheckoutStep = step;
            GoToStep(step);
            if (update == true)
            {
                CalculateTaxandShipping(Order, BillingAddress, ShippingAddress);
                updateCheckoutOrder(Order);
            }
        }

        protected void StoreAccountCheckoutNext_Click(object sender, EventArgs e)
        {
            int step = CheckoutStep;
            if (step < LastStep)
            {
                Page.Validate();
                if (Page.IsValid == true)
                {
                    bool update = step == 1;
                    step++;
                    CheckoutStep = step;
                    GoToStep(step);
                    if (update == true)
                    {
                        UpdateAddresses(BillingAddress, ShippingAddress);
                        CalculateTaxandShipping(Order, BillingAddress, ShippingAddress);
                        updateCheckoutOrder(Order);
                    }
                }
            }
        }

		#endregion

		#region Private Functions

        private void GoToStep(int Step)
        {
            // Reset steps classes
            liStepShipping.Attributes["class"] = "StoreCheckoutStep";
            liStepOrderReview.Attributes["class"] = "StoreCheckoutStep";
            liStepPayment.Attributes["class"] = "StoreCheckoutStep";
            // Switch to the required screen step
            switch (Step)
            {
                case 0: // Return to Store
                    Response.Redirect(Globals.NavigateURL(StoreSettings.StorePageID), true);
                    break;
                case 1: // Show Addresses
                    // Display required screen
                    divStoreCheckoutAddresses.Visible = true;
                    divStoreCheckoutCart.Visible = false;
                    divStoreCheckoutGateway.Visible = false;
                    // Set as active step
                    liStepShipping.Attributes["class"] = "StoreCheckoutActiveStep";
                    // Check if the Account fieldset have to be displayed
                    //if (StoreSettings.CheckoutMode == CheckoutType.UserChoice && IsLogged == false)
                    //{
                    //    fsAccountInfos.Visible = true;
                    //}
                    break;
                case 2: // Show Final Cart
                    // Display required screen
                    divStoreCheckoutAddresses.Visible = false;
                    divStoreCheckoutCart.Visible = true;
                    divStoreCheckoutGateway.Visible = false;
                    // Set as active step
                    liStepOrderReview.Attributes["class"] = "StoreCheckoutActiveStep";
                    StoreAccountCheckoutNext.Visible = true;
                    break;
                case 3: // Show Payment
                    // Display required screen
                    divStoreCheckoutAddresses.Visible = false;
                    divStoreCheckoutCart.Visible = false;
                    divStoreCheckoutGateway.Visible = true;
                    // Set as active step
                    liStepPayment.Attributes["class"] = "StoreCheckoutActiveStep";
                    StoreAccountCheckoutPrevious.Visible = false;
                    StoreAccountCheckoutNext.Visible = false;
                    break;
                case 4: // Return from payment or finished
                    // Display required screen
                    divStoreCheckoutAddresses.Visible = false;
                    divStoreCheckoutCart.Visible = false;
                    divStoreCheckoutGateway.Visible = true;
                    plhOrder.Visible = true;
                    plhCheckoutNavigation.Visible = false;
                    // Set as active step
                    liStepDone.Attributes["class"] = "StoreCheckoutActiveStep";
                    break;
                default:
                    break;
            }
        }

        private string OrderNavigation()
        {
            CustomerNavigation nav = new CustomerNavigation();
            nav.TabId = TabId;
            nav.PageID = "CustomerOrders";
            nav.CustomerID = Order.CustomerID;
            nav.OrderID = Order.OrderID;
            return nav.GetNavigationUrl();
        }

        private void updateOrderResult(string OrderProcessed)
        {
            // Update display
            lblOrderNumber.Text = String.Format(Localization.GetString("lblOrderNumber", this.LocalResourceFile), Order.OrderID);
            lblOrderProcessed.Text = OrderProcessed;
            if (IsLogged == true)
            {
                btnDisplayOrder.Text = Localization.GetString("btnDisplayOrder", this.LocalResourceFile);
                btnDisplayOrder.PostBackUrl = OrderNavigation();
            }
            else
                btnDisplayOrder.Visible = false;
            GoToStep(4);
        }

		/// <summary>
		/// This informs the checkout controls that the order has been updated.
		/// </summary>
		/// <param name="order"></param>
		private void updateCheckoutOrder(OrderInfo order)
		{
			if (order != null)
			{
				taxControl.Order = order;
				shippingControl.Order = order;
                lblGrandTotal.Text = order.GrandTotal.ToString("C", LocalFormat);
			}
		}

		/// <summary>
		/// Examine the module setting "RequireSSL" to determine if checkout should force a 
		/// redirect to HTTPS.
		/// </summary>
		/// <returns>true if HTTPS should be used</returns>
		private bool forceSSL()
		{
			// Determine if checkout should be forced to SSL according the module setting.
			string requireSSLSetting = (string)Settings["RequireSSL"];
			bool requireSSL = false;
			if ( requireSSLSetting != null && requireSSLSetting.Length > 0 )
			{
				try
				{
					requireSSL = bool.Parse(requireSSLSetting);
				}
				catch
				{
					requireSSL = false;
				}
			}
			return requireSSL;
		}

		///<summary>
		///Load the selected address checkout control and add to the address placeholder.
		///</summary>
		private void loadAddressControl() 
		{
			plhAddressCheckout.Controls.Clear();
            IAddressProvider addressProvider = StoreController.GetAddressProvider(StoreSettings.AddressName);
			addressCheckoutControl = (AddressCheckoutControlBase)addressProvider.GetCheckoutControl(this, ModulePath);
            addressCheckoutControl.ID = "addresscheckout";
            addressCheckoutControl.ModuleConfiguration = this.ModuleConfiguration;
            addressCheckoutControl.ShippingAddressChanged += new ShippingAddressChangedEventHandler(ctlAddressCheckout_ShippingAddressChanged);
            addressCheckoutControl.BillingAddressChanged += new BillingAddressChangedEventHandler(ctlAddressCheckout_BillingAddressChanged);
			plhAddressCheckout.Controls.Add(addressCheckoutControl);
		}

		private void loadCartControl()
		{
			plhCart.Controls.Clear();
            CartDetail cartControl = (CartDetail)LoadControl(ModulePath + "CartDetail.ascx");
            // Read module settings and define cart properties
            MainCartSettings cartSettings = new ModuleSettings(ModuleId, TabId).MainCart;
            cartControl.ShowThumbnail = cartSettings.ShowThumbnail;
            cartControl.ThumbnailWidth = cartSettings.ThumbnailWidth;
            cartControl.GIFBgColor = cartSettings.GIFBgColor;
            cartControl.EnableImageCaching = cartSettings.EnableImageCaching;
            cartControl.CacheImageDuration = cartSettings.CacheImageDuration;
            cartControl.ProductColumn = cartSettings.ProductColumn.ToLower();
            cartControl.LinkToDetail = cartSettings.LinkToDetail;
            cartControl.IncludeVAT = cartSettings.IncludeVAT;
            cartControl.TemplatePath = templatePath;
            cartControl.ID = "cartdetail";
            cartControl.ModuleConfiguration = ModuleConfiguration;
            cartControl.StoreSettings = StoreSettings;
			cartControl.EditComplete += new EventHandler(cartControl_EditComplete);
			plhCart.Controls.Add(cartControl);
		}

		private void loadShippingCheckoutControl()
		{
			plhShippingCheckout.Controls.Clear();
            IShippingProvider shippingProvider = StoreController.GetShippingProvider(StoreSettings.ShippingName);
			shippingControl = (ICheckoutControl)shippingProvider.GetCheckoutControl(this, ModulePath);
            shippingControl.StoreSettings = StoreSettings;
            shippingControl.IncludeVAT = _includeVAT;
			plhShippingCheckout.Controls.Add((ProviderControlBase)this.shippingControl);
		}

		private void loadTaxCheckoutControl() 
		{
			plhTaxCheckout.Controls.Clear();
            ITaxProvider taxProvider = StoreController.GetTaxProvider(StoreSettings.TaxName);
			taxControl = (ICheckoutControl)taxProvider.GetCheckoutControl(this, ModulePath);
            taxControl.StoreSettings = StoreSettings;
			plhTaxCheckout.Controls.Add((ProviderControlBase)this.taxControl);
		}

		private void loadPaymentControl()
		{
			GatewayController controller = new GatewayController(Server.MapPath(ModulePath));
            GatewayInfo gateway = controller.GetGateway(StoreSettings.GatewayName);

			if (gateway != null)
			{
                string controlPath = Path.Combine(gateway.GatewayPath, gateway.PaymentControl);
				if (File.Exists(controlPath))
				{
                    controlPath = controlPath.Replace(Server.MapPath(ModulePath), ModulePath).Replace(Path.DirectorySeparatorChar, '/');

					plhGateway.Controls.Clear();
					paymentControl = (PaymentControlBase)LoadControl(controlPath);
                    paymentControl.ID = gateway.PaymentControl.ToLower();
                    paymentControl.ModuleConfiguration = this.ModuleConfiguration;
                    paymentControl.StoreSettings = StoreSettings;
					paymentControl.CheckoutControl = this as ICheckoutControl;
                    paymentControl.EnableViewState = true;
                    paymentControl.AwaitingPayment += new EventHandler(paymentControl_AwaitingPayment);
                    paymentControl.PaymentRequiresConfirmation += new EventHandler(paymentControl_PaymentRequiresConfirmation);
					paymentControl.PaymentSucceeded += new EventHandler(paymentControl_PaymentSucceeded);
					paymentControl.PaymentCancelled += new EventHandler(paymentControl_PaymentCancelled);
					paymentControl.PaymentFailed += new EventHandler(paymentControl_PaymentFailed);
					plhGateway.Controls.Add(paymentControl);
				}
				else
				{
                    LiteralControl error = new LiteralControl("<span class=\"NormalRed\">" + Localization.GetString("ErrorCouldNotFind", this.LocalResourceFile) + " " + controlPath + ".</span>");
			
					plhGateway.Controls.Clear();
					plhGateway.Controls.Add(error);
				}
			}
			else
			{ 
                    LiteralControl error = new LiteralControl("<span class=\"NormalRed\">" + Localization.GetString("ErrorPaymentOption", this.LocalResourceFile) + "</span>");
			
					plhGateway.Controls.Clear();
					plhGateway.Controls.Add(error);				
			}
		}

		/// <summary>
		/// Retrieves the OrderID from the cookie if available; otherwise a -1 is returned
		/// </summary>
		/// <returns>OrderID if found in cookie; otherwise a -1 is returned.</returns>
		private int GetOrderIDFromCookie()
		{
			int orderID = Null.NullInteger;
            HttpCookie cookie = HttpContext.Current.Request.Cookies[CookieKey];
            if ((cookie != null) && (cookie["OrderID"] != null))
            {
                string cookieValue = cookie["OrderID"];
                if (string.IsNullOrEmpty(cookieValue) == false)
                {
                    // Verify if it's a valid integer
                    int value;
                    bool isInteger = int.TryParse(cookieValue, out value);
                    // If it's NOT an integer, try to decrypt the value
                    if (isInteger == false)
                    {
                        string decrypted = SymmetricHelper.Decrypt(cookieValue);
                        orderID = int.Parse(decrypted);
                    }
                    else
                        orderID = value;
                }
            }
			return orderID;
		}

		private void SetOrderIdCookie(int OrderID)
		{
            HttpCookie cookie = HttpContext.Current.Request.Cookies[CookieKey];
            if (cookie == null)
                cookie = new HttpCookie(CookieKey);
            string cookieValue;
            if (StoreSettings.SecureCookie == true && SymmetricHelper.CanSafelyEncrypt == true)
                cookieValue = SymmetricHelper.Encrypt(OrderID.ToString());
            else
                cookieValue = OrderID.ToString();
            cookie["OrderID"] = cookieValue;
            HttpContext.Current.Response.Cookies.Add(cookie);
		}

		private string CookieKey
		{
            get { return CookieName + PortalId.ToString(); }
		}

		/// <summary>
		/// Calculate the tax and shipping cost for the order.
		/// </summary>
		/// <param name="order"></param>
        private void CalculateTaxandShipping(OrderInfo order, IAddressInfo billingAddress, IAddressInfo shippingAddress)
		{
			if (order != null)
			{
                List<ItemInfo> cartItems = CurrentCart.GetItems(PortalId, StoreSettings.SecureCookie);

                //Shipping...
                IShippingProvider shippingProvider = StoreController.GetShippingProvider(StoreSettings.ShippingName);
                IShippingInfo shippingInfo = shippingProvider.CalculateShippingFee<ItemInfo>(PortalId, billingAddress, shippingAddress, cartItems);

                if (shippingInfo == null)
                {
                    plhCheckout.Visible = false;
                    lblError.Text = String.Format(Localization.GetString("ErrorShippingRates", this.LocalResourceFile), StoreSettings.DefaultEmailAddress);
                    plhError.Visible = true;
                    return;
                }
                else
                {
                    plhCheckout.Visible = true;
                    plhError.Visible = false;

                    //PayPal Surcharges...
                    if (StoreSettings.GatewayName == "PayPalProvider")
                    {
                        PayPalSettings payPalSettings = new PayPalSettings(StoreSettings.GatewaySettings);
                        decimal m_FixedSurcharge = payPalSettings.SurchargeFixed;
                        decimal m_PercentSurcharge = payPalSettings.SurchargePercent;
                        order.ShippingCost = shippingInfo.Cost + m_FixedSurcharge + ((order.OrderTotal + shippingInfo.Cost + m_FixedSurcharge) * (m_PercentSurcharge / 100));
                        shippingInfo.Cost = order.ShippingCost;
                    }
                    else
                        order.ShippingCost = shippingInfo.Cost;

                    if (order.ShippingCost > 0)
                        plhShippingCheckout.Visible = true;
                    else
                        plhShippingCheckout.Visible = false;
                }

                //Tax...
                ITaxProvider taxProvider = StoreController.GetTaxProvider(StoreSettings.TaxName);

                ITaxInfo taxInfo = taxProvider.CalculateSalesTax(PortalId, cartItems, shippingInfo, shippingAddress);
                if (taxInfo.ShowTax && taxInfo.SalesTax > 0)
                {
                    plhTaxCheckout.Visible = true;
                    order.TaxTotal = taxInfo.SalesTax;
                    order.ShippingTax = taxInfo.ShippingTax;
                }
                else
                {
                    plhTaxCheckout.Visible = false;
                    order.TaxTotal = 0;
                    order.ShippingTax = 0;
                }
			}
		}

		/// <summary>
		/// Retrieve the current order and addresses from the database.
		/// </summary>
		/// <returns></returns>
        private OrderInfo GetExistingOrder(int orderID, bool updateDetails)
		{
            OrderInfo order = null;

            if (orderID != Null.NullInteger)
			{				
				try
				{
					order = orderController.GetOrder(PortalId, orderID);
                    if (order != null)
                    {
                        // Update order details if needed
                        if (updateDetails == true)
                            order = orderController.UpdateOrderDetails(order.OrderID, CurrentCart.GetInfo(PortalId, StoreSettings.SecureCookie).CartID);
                        // Load billing address or create a new one
                        IAddressInfo billingAddress = null;
                        int billingAddressID = order.BillingAddressID;
                        if (billingAddressID != Null.NullInteger)
                            billingAddress = addressController.GetAddress(order.BillingAddressID);
                        if (billingAddress != null)
                            BillingAddress = billingAddress;
                        else
                            BillingAddress = new AddressInfo();
                        // Load shipping address or create a new one
                        IAddressInfo shippingAddress = null;
                        int shippingAddressID = order.ShippingAddressID;
                        if (shippingAddressID != Null.NullInteger && shippingAddressID != billingAddressID)
                            shippingAddress = addressController.GetAddress(shippingAddressID);
                        if (shippingAddress != null)
                            ShippingAddress = shippingAddress;
                        else
                            ShippingAddress = new AddressInfo();
                    }
				}
				catch 
				{
					order = null;	
				}
			}

			return order;
		}

		private OrderInfo CreateOrder()
		{
            // Get current cart ID
            string cartID = CurrentCart.GetInfo(PortalId, StoreSettings.SecureCookie).CartID;

            // Associate cart with this user or with impersonated user
			CartController cartController = new CartController();
            if (IsLogged == true)
                cartController.UpdateCart(cartID, UserId);
            else
                cartController.UpdateCart(cartID, StoreSettings.ImpersonatedUserID);

			// Create order from cart content
            OrderInfo order = orderController.CreateOrder(cartID);
			if (order != null)
			{
				SetOrderIdCookie(order.OrderID);
                BillingAddress = new AddressInfo();
                ShippingAddress = new AddressInfo();
            }

			return order;
		}

        private void UpdateAddresses(IAddressInfo billingAddress, IAddressInfo shippingAddress)
        {
            OrderInfo order = Order;
            bool updateOrder = false;
            int currentUser;

            // Define the current user ID
            if (IsLogged == true)
                currentUser = UserId;
            else
                currentUser = StoreSettings.ImpersonatedUserID;

            // If the user state has changed
            if (order.CustomerID != currentUser)
                updateOrder = true;
            if (billingAddress.AddressID != Null.NullInteger && billingAddress.UserID != currentUser)
            {
                // If address was user saved, create a new one
                if (billingAddress.UserSaved == true)
                {
                    billingAddress.AddressID = Null.NullInteger;
                    billingAddress.UserSaved = false;
                }
                billingAddress.UserID = currentUser;
                billingAddress.Modified = true;
                updateOrder = true;
            }
            if (shippingAddress.AddressID != Null.NullInteger && shippingAddress.UserID != currentUser)
            {
                // If address was user saved, create a new one
                if (shippingAddress.UserSaved == true)
                {
                    shippingAddress.AddressID = Null.NullInteger;
                    shippingAddress.UserSaved = false;
                }
                shippingAddress.UserID = currentUser;
                shippingAddress.Modified = true;
                updateOrder = true;
            }

            // Add or update billing address
            int billingAddressID = billingAddress.AddressID;
            if ((billingAddressID == Null.NullInteger && billingAddress.Modified == true) || billingAddressID == 0)
            {
                billingAddress.PortalID = this.PortalId;
                billingAddress.UserID = currentUser;
                if (string.IsNullOrEmpty(billingAddress.Description) == true)
                    billingAddress.Description = string.Format(Localization.GetString("BillingDescription", LocalResourceFile), Order.OrderID);
                billingAddressID = addressController.AddAddress(billingAddress);
                BillingAddress = addressController.GetAddress(billingAddressID);
            }
            else if (billingAddressID != Null.NullInteger && billingAddress.Modified == true)
            {
                addressController.UpdateAddress(billingAddress);
            }
            if (billingAddressID != Order.BillingAddressID)
                updateOrder = true;

            // Add or update shipping address
            int shippingAddressID = shippingAddress.AddressID;
            if (shippingAddressID != billingAddressID)
            {
                if ((shippingAddressID == Null.NullInteger && shippingAddress.Modified == true) || shippingAddressID == 0)
                {
                    shippingAddress.PortalID = this.PortalId;
                    shippingAddress.UserID = currentUser;
                    if (string.IsNullOrEmpty(shippingAddress.Description) == true)
                        shippingAddress.Description = string.Format(Localization.GetString("ShippingDescription", LocalResourceFile), Order.OrderID);
                    shippingAddressID = addressController.AddAddress(shippingAddress);
                    ShippingAddress = addressController.GetAddress(shippingAddressID);
                }
                else if (shippingAddressID != Null.NullInteger && shippingAddress.Modified == true)
                {
                    addressController.UpdateAddress(shippingAddress);
                }
                else if (shippingAddressID == Null.NullInteger && shippingAddress.Modified == false)
                    shippingAddressID = billingAddressID;
                if (shippingAddressID != Order.ShippingAddressID)
                    updateOrder = true;
            }

            // Update order if needed
            if (updateOrder == true)
                orderController.UpdateOrder(Order.OrderID, Order.OrderDate, Order.OrderNumber, shippingAddressID, billingAddressID, Order.TaxTotal, Order.ShippingCost, currentUser);
        }

		#endregion

		#region ICheckoutControl Members

        public void Hide() 
        {
            plhCheckout.Visible = false;
        }

        public void HidePrevious()
        {
            StoreAccountCheckoutPrevious.Visible = false;
        }

		public IAddressInfo BillingAddress
		{
			get
			{
                if (addressCheckoutControl != null)
                    return addressCheckoutControl.BillingAddress;
                else
                    return null;
			}
			set
			{
                if (addressCheckoutControl != null)
                    addressCheckoutControl.BillingAddress = value;
			}
		}

		public IAddressInfo ShippingAddress
		{
			get
			{
                if (addressCheckoutControl != null)
                    return addressCheckoutControl.ShippingAddress;
                else
                    return null;
			}
			set
			{
                if (addressCheckoutControl != null)
                    addressCheckoutControl.ShippingAddress = value;
			}
		}

        public OrderInfo Order
        {
            get { return _order; }
            set { _order = value; }
        }

        public bool IncludeVAT
        {
            get { return _includeVAT; }
            set { _includeVAT = value; }
        }

		/// <summary>
		/// Calculate the final order and place it into a "waiting for payment" state.
		/// </summary>
		/// <returns>OrderInfo with the final cart, tax, and shipping totals.</returns>
		public OrderInfo GetFinalizedOrderInfo()
		{
            OrderInfo order = Order;
            IAddressInfo billingAddress = BillingAddress;
            int billingAddressID = billingAddress.AddressID;
            IAddressInfo shippingAddress = ShippingAddress;
            int shippingAddressID = shippingAddress.AddressID;

			// Update tax and shipping.
            CalculateTaxandShipping(order, billingAddress, shippingAddress);

			// Save order details
            orderController.UpdateOrder(order.OrderID, System.DateTime.Now,
                "",
                shippingAddressID,
                billingAddressID,
                order.TaxTotal,
                order.ShippingCost,
                true,
                (int)OrderInfo.OrderStatusList.AwaitingPayment,
                order.CustomerID);

            return Order;
		}

        public OrderInfo GetOrderDetails()
        {
            return orderController.GetOrder(PortalId, Order.OrderID);
        }

		#endregion

        #region IStoreTabedControl Members

        string IStoreTabedControl.Title
        {
            get { return Localization.GetString("lblParentTitle", this.LocalResourceFile); }
        }

        #endregion
    }
}
